/*
 * Jay Fernandez & Craig Markham
 * June 9, 2011
 * TCSS 371
 * Project
 *
 * DESCRIPTION
 * An LC-3 compiler to
 * convert a .asm to .obj file.
 */

#include <stdio.h>
#include <string.h>
#include "opMethods.h"

#define MAX 100

struct symbol {
	char *name;
	int address;
};
struct symbol symbols[MAX];
int num_labels = 0;

void findSymbols(const FILE*);
void findCommands(const FILE*);

typedef enum commands commands;
enum commands {
	//LC3 Pseudo OPCODE listed first for simplicity - 1
	ORIG,
	//LC3 OPCODES - 16
	ADD, AND, BR, JMP, JSR, JSRR, LD, LDI, LDR, LEA, NOT, RET, RTI, ST, STI, STR,
	//LC3 Pseudo OPCODES - 5
	FILL, STRINGZ, GLOBAL, BLKW, END,
	//LC3 TRAP CODES - 8
	 BLOCK, HALT, GETC, IN, OUT, PUTS, PUTSP,
	//LC3 Extra OPCODES - 3
	NEG, PUSH, POP,
	// Size
	NUM_OPS
} ;

static const char* const opnames[NUM_OPS] = {
	//LC3 Pseudo OPCODE listed first for simplicity - 1
	".ORIG",
	//LC3 OPCODES - 16
	"ADD", "AND", "BR", "JMP", "JSR", "JSRR", "LD", "LDI", "LDR", "LEA", "NOT", "RET", "RTI", "ST", "STI", "STR",
	//LC3 Pseudo OPCODES - 5
	".FILL", ".STRINGZ", "GLOBAL", "BLKW", ".END",
	//LC3 TRAP CODES - 7
	 ".BLOCK",  "HALT", "GETC", "IN", "OUT", "PUTS", "PUTSP",
	//LC3 Extra OPCODES - 3
	"NEG", "PUSH", "POP",
};

int main (int argc, const char * argv[]) {
	FILE* fp;

	if ((fp = fopen("13-14.asm","r")) == NULL) {
		printf("error Read File could not be opened \n");
	}
	findSymbols(fp);
	rewind(fp);
//	findCommands(fp);

    return 0;
}
void findCommands(const FILE* fp){
	//TODO: determine how to check for line size vice using MAX
	char line[MAX];
	char *tokenPtr, *arg1Ptr, *arg2Ptr;
	int tempBinary = 0;
	char *comment = ";";
	char toks[] = "\n\r\t ,"; // newlines, carriage return, tabs, spaces and commas
	int size = 0;

//	int first_line = 1;
	while (fgets(line, 100, fp)) {	//get next file line
		tokenPtr = strtok(line, toks);
/*		int first_token = 1;
		//for first line w/valid code only, set starting line num
		if(first_line == 1 && tokenPtr != NULL && (strcmp(tokenPtr, comment))){
			tokenPtr = strtok(NULL, toks);
			//TODO: Add error check for valid line number
			tokenPtr = strtok(NULL, toks);
			printf("line num hex: %hx\n", loc_count);
			first_line = 0;
		}*/

		while (tokenPtr != NULL && (strcmp(tokenPtr, comment))) {
			int i;
			tempBinary = 0;
			for (i = 0; i < NUM_OPS - 1; i++) {
				if(i == 3 && (strncmp(tokenPtr, opnames[i], 2) == 0)){
				}
				if(strcmp(tokenPtr, opnames[i]) == 0){
					int op_cmd = i;
//					printf("op_cmd i = %d\n", i);
					//add switch statement for all commands HERE
					switch(op_cmd) {
					case 0: // .ORIG
						// i = 0; .ORIG
//						loc_count = strtol((tokenPtr = strtok(NULL, toks)), NULL, 16);
//						printf("line num hex: %hx\n", loc_count);
						break;

					case 1: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
//						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
//						printf("%hx	ADD\n", loc_count);
						break;

					case 2: //AND
						arg1Ptr = tokenPtr;
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opBR(tokenPtr, arg1Ptr);
//						printf("%hx	AND\n", loc_count);
						break;

/*					case 3: //BR
						size = strlen(tokenPtr);
						int j;
						for(j = 2; j < size; j++){
							arg1Ptr[i - 2] = tokenPtr[i];
						}
						printf("BR nzp: %s", arg1Ptr);

						arg2Ptr = strtok(NULL, toks);//Offset
						tempBinary = opBR(arg1Ptr, arg2Ptr);
						printf("%hx	BR", loc_count);
						break;

					case 4: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	4", loc_count);
						break;

					case 5: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	5", loc_count);
						break;

					case 6: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	6", loc_count);
						break;

					case 7: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	7", loc_count);
						break;

					case 8: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	8", loc_count);
						break;

					case 9: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	9", loc_count);
						break;

					case 10: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	0", loc_count);
						break;

					case 11: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	1", loc_count);
						break;

					case 12: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	2", loc_count);
						break;

					case 13: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	3", loc_count);
						break;

					case 14: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	4", loc_count);
						break;

					case 15: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	5", loc_count);
						break;

					case 16: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	6", loc_count);
						break;

					case 17: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	7", loc_count);
						break;

					case 18: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	8", loc_count);
						break;

					case 19: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	9", loc_count);
						break;

					case 20: //ADD
						arg1Ptr = strtok(NULL, toks);
						arg2Ptr = strtok(NULL, toks);
						tempBinary = opADD(tokenPtr, arg1Ptr, arg2Ptr);
						printf("%hx	0", loc_count);
						break;*/
					}


				}
			}
			tokenPtr = strtok(NULL, toks);		//read next token from line
		}
		//printf("line num hex: %hx\n", loc_count);
	}

}

void findSymbols(const FILE* fp){
	char line[MAX];
	char *tokenPtr;
	char *comment = ";";
	char toks[] = "\n\r\t ,"; // newlines, carriage return, tabs, spaces and commas
	int cmd[MAX];
	int first_line = 1;
	long loc_count = 0;
	int num_cmd = 0;

	printf("NUM_OPS: %d\n", NUM_OPS);

	while (fgets(line, 100, fp)) {	//get next file line
		tokenPtr = strtok(line, toks);
		int first_token = 1;

		//for first line w/valid code only, verify first valid token is ".ORIG"
		if(first_line == 1 && tokenPtr != NULL && (strcmp(tokenPtr, comment))){
			if(strcmp(tokenPtr, opnames[0]) != 0){
				printf("error msg, no .orig\n");
				return;
			}
			//set starting line value
			//TODO: Add error check for valid line number
			loc_count = strtol((tokenPtr = strtok(NULL, toks)), NULL, 16);
			tokenPtr = strtok(NULL, toks);
			first_line = 0;
			printf("loc_count: %hx\n", loc_count);

		}

		while (tokenPtr != NULL && (strcmp(tokenPtr, comment))) {
			int cmd_found = 0;
			int i;
			for (i = 0; i < NUM_OPS - 1; i++) {
				if(i == 3 && (strncmp(tokenPtr, opnames[i], 2) == 0)){
					cmd[num_cmd++] = i;
					cmd_found = 1;
					loc_count++;
				}
				if(strcmp(tokenPtr, opnames[i]) == 0){
					cmd[num_cmd++] = i;
					cmd_found = 1;
					loc_count++;

				}

				if(i > 28){
					//TODO: Add extra loc-count for each extra cmd
					if(i == 29){						// NEG cmd
						loc_count = loc_count + 2;
					} else if (i == 30){					//PUSH cmd
						loc_count = loc_count + 3;
					} else {							//POP cmd
						loc_count = loc_count + 4;
					}
				}
			}
			if(first_token && !cmd_found){		//check for label
				if ((symbols[num_labels].name = malloc(strlen(tokenPtr) + 1)) == NULL) {
				    perror("malloc");
				}
				strcpy(symbols[num_labels].name, tokenPtr);
				symbols[num_labels++].address = loc_count;
			}
			tokenPtr = strtok(NULL, toks);		//read next token from line
			first_token = 0;
		}
	}

	printf("Num Commands found: %d\n", num_cmd);
	int i;
	for (i = 0; i < num_cmd; i++) {
			printf("Command found: %s\n", opnames[cmd[i]]);
	}
	printf("Num labels found: %d\n", num_labels);

	for (i = 0; i < num_labels; i++) {
		printf("label address: %hx	", symbols[i].address);
		printf("loop label name: %s\n", symbols[i].name);

	}
}

